package zdingtalk

import (
	"errors"
	"gitee.com/zjlsliupei/ghelp"
	"github.com/beego/beego/v2/client/httplib"
	"sort"
	"strconv"
	"strings"
	"time"
)

type Option struct {
	Domain    string
	AppKey    string
	AppSecret string
}

var GlobalOption Option

func Config(o Option) {
	if o.Domain == "" {
		o.Domain = "https://openplatform.dg-work.cn"
	}
	GlobalOption = o
}

type ZDingTalk struct {
	header map[string]string
	path   string
	params []map[string]string
	method string
}

func NewZDingTalk() *ZDingTalk {
	z := ZDingTalk{}
	z._init()
	return &z
}

func (__ *ZDingTalk) _init() {
	__.header = make(map[string]string)
	//ip, _ := ghelp.GetIP()
	__.SetHeader("X-Hmac-Auth-IP", "127.0.0.1")
	//__.SetHeader("X-Hmac-Auth-IP", ip.String())
	//interfaces, _ := net.Interfaces()
	//__.SetHeader("X-Hmac-Auth-MAC", interfaces[0].HardwareAddr.String())
	__.SetHeader("X-Hmac-Auth-MAC", "")
	__.SetHeader("X-Hmac-Auth-Timestamp", time.Now().Format("2006-01-02T15:04:05.000+08:00"))
	__.SetHeader("X-Hmac-Auth-Version", "1.0")
	__.SetHeader("X-Hmac-Auth-Nonce", strconv.FormatInt(time.Now().UnixNano(), 10))
	__.SetHeader("apiKey", GlobalOption.AppKey)
}

// SetHeader 设置请求头
func (__ *ZDingTalk) SetHeader(key, val string) *ZDingTalk {
	__.header[key] = val
	return __
}

// SetPath 设置请求路径
func (__ *ZDingTalk) SetPath(path string) *ZDingTalk {
	__.path = path
	return __
}

// AddParameter 增加参数
func (__ *ZDingTalk) AddParameter(key, val string) *ZDingTalk {
	__.params = append(__.params, map[string]string{
		"key": key,
		"val": val,
	})
	return __
}

// Do 执行请求
// method: 请求方法，可选POST, GET
func (__ *ZDingTalk) Do(method string) (string, error) {
	__.method = strings.ToUpper(method)
	buildStr := __.buildParams(__.sortParams())
	var url string = GlobalOption.Domain + __.path
	var req *httplib.BeegoHTTPRequest
	switch __.method {
	case "POST":
		req = httplib.Post(url)
		req.Body(buildStr)
	case "GET":
		if buildStr != "" {
			url += "?" + buildStr
		}
		req = httplib.Get(url)
	default:
		return "", errors.New(__.method + " is not support")
	}
	__.SetHeader("X-Hmac-Auth-Signature", __.sign())
	for k, v := range __.header {
		req.Header(k, v)
	}
	return req.String()
}

// buildParams
func (__ *ZDingTalk) buildParams(params []map[string]string) string {
	var buildStr string
	for _, v := range params {
		buildStr += v["key"] + "=" + v["val"] + "&"
	}
	return strings.TrimRight(buildStr, "&")
}

// sign 生成签名
func (__ *ZDingTalk) sign() string {
	str := __.method + "\n"
	str += __.header["X-Hmac-Auth-Timestamp"] + "\n"
	str += __.header["X-Hmac-Auth-Nonce"] + "\n"
	str += __.path + "\n"
	str += __.buildParams(__.sortParams())
	return ghelp.HmacSha256(str, GlobalOption.AppSecret)
}

// sort 排序
// * HttpRequestParams
//    HTTP中POST和GET的参数，对其排序,忽略大小写的字典序排列。
//    然后组装key1=value1&key2=value2。
//    注意：如果出现类似key=value2&key=value1&key=value3时情况，请对值列表排序（升序），
//         变成key=value1&key=value2&key=value3。
func (__ *ZDingTalk) sortParams() []map[string]string {
	var keyVals = make(map[string]map[string]string)
	var keys []string
	for _, v := range __.params {
		_key := v["key"] + "-" + v["val"]
		keys = append(keys, _key)
		keyVals[_key] = v
	}
	sort.Strings(keys)
	var newMap []map[string]string
	for _, v := range keys {
		newMap = append(newMap, keyVals[v])
	}
	return newMap
}
